package com.onepower.core.modules.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.onepower.core.domain.AuthUser;
import com.onepower.core.domain.mapper.SysUserInfoMapper;
import com.onepower.core.domain.request.MatchAdminForm;
import com.onepower.core.domain.request.SysUserForm;
import com.onepower.core.domain.response.MatchAdminInfo;
import com.onepower.core.domain.response.SysUserInfo;
import com.onepower.core.exception.BizException;
import com.onepower.core.modules.repository.entity.MatchReferee;
import com.onepower.core.modules.repository.entity.SysUser;
import com.onepower.core.modules.repository.entity.SysUserRole;
import com.onepower.core.modules.repository.mapper.SysUserMapper;
import com.onepower.core.modules.service.IMatchRefereeService;
import com.onepower.core.modules.service.ISysMenuService;
import com.onepower.core.modules.service.ISysUserRoleService;
import com.onepower.core.modules.service.ISysUserService;
import com.onepower.core.result.BaseResultCode;
import com.onepower.core.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 系统用户表 服务实现类
 * </p>
 *
 * @author kin
 * @since 2018-08-01
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private ISysMenuService sysMenuService;

    @Autowired
    private ISysUserRoleService userRoleService;

    @Autowired
    private IMatchRefereeService matchRefereeService;

    @Override
    public AuthUser login(String account, String password) {
        SysUser sysUser = this.getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getAccount, account)
                .eq(SysUser::getPassword, password)
        );

        if (sysUser == null) {
            throw new BadCredentialsException(BaseResultCode.ACCOUNT_PASSWORD_ERROR.getMsg());
        }

        MatchReferee referee = matchRefereeService.getReferee(sysUser.getId());
        if (referee != null) {
            if (referee.getIsLogin() > 0) {
                throw new DisabledException(BaseResultCode.HAS_LOGIN.getMsg());
            }
        }

        return SysUserInfoMapper.MAPPER.converterAuth(sysUser);
    }

    @Transactional
    @Override
    public void saveUser(SysUserForm userInfo) {
        if (StringUtils.isEmpty(userInfo.getAccount())) {
            throw new BizException(BaseResultCode.INVALID_PARAMETER);
        }

        if (userInfo.getId() == null) {
            userInfo.setPassword(SecurityUtils.generatorPass());
            userInfo.setStatus(0);
            userInfo.setCreateUserId(SecurityUtils.getCurrentUserId());
            this.save(userInfo);
        } else {
            userInfo.setPassword(null);
            userInfo.setUpdateUserId(SecurityUtils.getCurrentUserId());
            this.updateById(userInfo);
            userRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userInfo.getId()));
        }
        userRoleService.saveBatch(userRoleList(userInfo));
    }

    @Transactional
    @Override
    public void deleteUser(List<Integer> ids) {
        this.removeByIds(ids);
        userRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, ids));
    }

    @Override
    public SysUserInfo getUser(Integer userId) {
        SysUserInfo sysUserInfo = SysUserInfoMapper.MAPPER.converter(this.getById(userId));
        List<SysUserRole> userRoleList = userRoleService.list(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        sysUserInfo.setRoleList(userRoleList.stream().map(x -> x.getRoleId().toString()).collect(Collectors.toList()));
        sysUserInfo.setPerms(sysMenuService.getPerms(userId));
        sysUserInfo.setMatchReferee(matchRefereeService.getReferee(userId));
        return sysUserInfo;
    }

    @Override
    public Page<SysUserInfo> getUserList(Page<SysUserInfo> page) {
        List<SysUser> sysUsers = baseMapper.selectUserList(page, Arrays.asList("MATCH_ADMIN", "MATCH_REFEREE"), SecurityUtils.getCurrentUserId());
        return page.setRecords(SysUserInfoMapper.MAPPER.converterList(sysUsers));
    }

    @Override
    public void restPassword(Integer userId, String password) {
        SysUser sysUser = new SysUser();
        sysUser.setId(userId);
        sysUser.setPassword(password);
        baseMapper.updateById(sysUser);
    }

    @Override
    public Page<MatchAdminInfo> getMatchAdminList(Page<MatchAdminInfo> page, Integer matchId) {
        List<MatchAdminInfo> sysUsers = baseMapper.selectMatchAdminList(page, matchId);
        return page.setRecords(sysUsers);
    }

    @Transactional
    @Override
    public void saveMatchAdmin(MatchAdminForm matchAdminForm) {
        SysUser sysUser = new SysUser();
        sysUser.setNickName(matchAdminForm.getNickName());
        sysUser.setAccount(matchAdminForm.getAccount());
        sysUser.setPassword(SecurityUtils.generatorPass());
        sysUser.setCreateUserId(SecurityUtils.getCurrentUserId());
        sysUser.setExpiryDate(new Date());
        baseMapper.insert(sysUser);

        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getId());
        sysUserRole.setRoleId(5);
        userRoleService.save(sysUserRole);

        MatchReferee referee = new MatchReferee();
        referee.setMatchId(matchAdminForm.getMatchId());
        referee.setMatchAdminId(sysUser.getId());
        referee.setRefereeId(-1);
        matchRefereeService.save(referee);
    }

    private List<SysUserRole> userRoleList(SysUserForm userInfo) {
        List<SysUserRole> userRoleList = new ArrayList<>();
        userInfo.getRoleIdList().forEach(x -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userInfo.getId());
            sysUserRole.setRoleId(x);
            userRoleList.add(sysUserRole);
        });

        return userRoleList;
    }
}
